package com.jinbai.searcher.web.search_web;

//import io.swagger.annotations.Api;
//import io.swagger.annotations.ApiImplicitParam;
//import io.swagger.annotations.ApiImplicitParams;
//import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.ansj.domain.Term;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.ansj.splitWord.analysis.ToAnalysis;

import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Controller
//@Api(tags = "搜索控制器")
public class SearchController {
	private final SearchMapper mapper;
	private final DescBuilder descBuilder;

	public SearchController(SearchMapper mapper, DescBuilder descBuilder) {
		this.mapper = mapper;
		this.descBuilder = descBuilder;
	}


//	@ApiImplicitParams({
//			@ApiImplicitParam(name = "query", value = "查询语句", example = "list", dataType = "String", required = true),
//			@ApiImplicitParam(name = "pageString", value = "分页起始数据", example = "1", dataType = "String", required = false)
//	})
	@GetMapping("/web")
//	@ApiOperation("分页查询文档信息")
	public String search(String query, @RequestParam(value = "page", required = false) String pageString, Model model) {
		log.debug("查询：query = {} ", query);

		// 参数的合法性检查 + 处理
		if (query == null) {
			log.debug("query 为 null，重定向到首页");
			return "redirect:/";
		}

		query = query.trim().toLowerCase(); // 必须转换成小写，anjs分词的时候将所有词语都装换成小写了
		if (query.isEmpty()) {
			log.debug("query 为空字符串，重定向到首页");
			return "redirect:/";
		}

		// 分词
		List<String> queryList = ToAnalysis.parse(query)
				.getTerms()
				.stream()
				.map(Term::getName)
				.collect(Collectors.toList());
		if (queryList.isEmpty()) {
			log.debug("query 分词后一个词都没有，重定向到首页");
			return "redirect:/";
		}

//		query = queryList.get(0);

		log.debug("进行查询的词：{}", queryList);

		int limit = 20;
		int offset = 0;
		int page = 1;
		if (pageString != null) {
			pageString = pageString.trim();
			try {
				page = Integer.parseInt(pageString);
				if (page <= 0) {
					page = 1;
				}

//				offset = (page - 1) * limit;
				limit = page * 20;  // 分别对这其中的词都查询page页
			} catch (NumberFormatException ignored) {}
		}

		log.debug("limit = {}, offset = {}, page = {}", limit, offset, page);

		// 获取各词的分页信息 + 权重  用于重排序
		List<DocumentWithWeight> documentWithWeightList = new ArrayList<>();
		for (String word : queryList) {
			List<DocumentWithWeight> curList = mapper.queryWithWeight(word, limit, offset);
			documentWithWeightList.addAll(curList);
		}

		Map<Integer, DocumentWithWeight> documentWithWeightMap = new HashMap<>();
		for (DocumentWithWeight documentWithWeight : documentWithWeightList) {
			int docId = documentWithWeight.getDocId();
			if (documentWithWeightMap.containsKey(docId)) {
				DocumentWithWeight curDocWe = documentWithWeightMap.get(docId);
				curDocWe.setWeight(curDocWe.getWeight() + documentWithWeight.getWeight());
				continue;
			}
			documentWithWeightMap.put(docId, new DocumentWithWeight(documentWithWeight));
		}

		List<DocumentWithWeight> list = new ArrayList<>(documentWithWeightMap.values());
//		List<Document> documentList = mapper.query(query, limit, offset);

		Collections.sort(list, (item1, item2) -> {
			return  item2.getWeight() - item1.getWeight();
		});

		int from = (page - 1) * 20;
		int to = Math.min(from + 20, list.size());

		List<DocumentWithWeight> subList = list.subList(from, to);
		List<Document> documentList = subList.stream()
				.map(DocumentWithWeight::convertToDocument)
				.collect(Collectors.toList());


		if (documentList.isEmpty()) {
			log.debug("我是有底线的~");
			documentList = mapper.query(query, limit, 0);
		}
		// 根据分词上下文生成文档的描述
		// lambda 中无法使用非 final 变量
		List<String> wordList = queryList;
		documentList = documentList.stream()
				.map(doc -> descBuilder.buildList(wordList, doc))
				.collect(Collectors.toList());

		// 将数据渲染到 model 中
		model.addAttribute("query", query);
		model.addAttribute("docList", documentList);
		model.addAttribute("page", page);
		return "search";
	}
}
